package com.xyzwps.server.paimon.it

import com.xyzwps.server.paimon.app.dto.Me
import com.xyzwps.server.paimon.jackson.JSON
import com.xyzwps.server.paimon.common.Utils
import org.springframework.http.MediaType
import org.springframework.test.web.reactive.server.WebTestClient
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.Assertions.assertNotNull

open class MvcTestBase(port: Int) {

    protected val webClient: WebTestClient = UiTestHelper.createWebTestClient("http://localhost:$port")

    private data class Env(
        var me: Me? = null,
        var registerDkey: String? = null,
        var loginDkey: String? = null
    )

    protected fun registerAndLogin(): Pair<Me, String> {
        val phone = UiTestHelper.genPhone()
        val env = Env()

        webClient.post().uri("/apis/register/send-vcode")
            .contentType(MediaType.APPLICATION_JSON)
            .bodyValue(mapOf("phone" to phone))
            .exchange()
            .expectStatus().isOk
            .expectBody()
            .jsonPath("$.data").value<String> { dkey -> env.registerDkey = dkey }
        assertNotNull(env.registerDkey)

        webClient.post().uri("/apis/register")
            .contentType(MediaType.APPLICATION_JSON)
            .bodyValue(mapOf("phone" to phone, "vcode" to "666666", "dkey" to env.registerDkey))
            .exchange()
            .expectStatus().isOk
            .expectBody()
            .jsonPath("$.data").isEmpty()

        webClient.post().uri("/apis/login/send-vcode")
            .contentType(MediaType.APPLICATION_JSON)
            .bodyValue(mapOf("phone" to phone))
            .exchange()
            .expectStatus().isOk
            .expectBody()
            .jsonPath("$.data").value<String> { dkey -> env.loginDkey = dkey }
        assertNotNull(env.loginDkey)

        webClient.post().uri("/apis/login")
            .contentType(MediaType.APPLICATION_JSON)
            .bodyValue(mapOf("phone" to phone, "vcode" to "666666", "dkey" to env.loginDkey))
            .exchange()
            .expectStatus().isOk
            .expectBody()
            .jsonPath("$.data")
            .value<Any> {
                val me = JSON.parse(JSON.stringify(it), Me::class)
                assertNotNull(me.id)
                assertEquals(Utils.maskPhone(phone), me.nickname)
                assertNotNull(me.createdAt)
                assertNotNull(me.token)
                env.me = me
            }

        return (env.me!! to env.me!!.token!!)
    }
}
